<?php


namespace EchoPHP\Redis;


class PhpRedisConnection {

    protected $client;

    /**
     * 创建PhpRedis连接器
     * PhpRedisConnection constructor.
     * @param \Redis $client
     */
    public function __construct($client) {
        $this->client = $client;
    }

    /**
     * redis命令统一执行入口，可以通过此方法进行redis操作，如有需要可以在此处添加相关日志记录
     * @param $method
     * @param array $parameters
     * @return mixed
     */
    public function command($method, array $parameters = []) {
        $result = $this->client->{$method}(...$parameters);

        return $result;
    }

    /**
     * 遍历获取键名
     * @param null $pattern
     * @param int $scanCount
     * @return array
     */
    public function scanKeys($pattern = null, $scanCount = 0) {
        $keys = [[]];
        $iterator = null;

        while ($scanKeys = $this->client->scan($iterator, $pattern, $scanCount)) {
            $keys[] = $scanKeys;
        }
        return array_merge(...$keys);
    }

    /**
     * 键值遍历 通过command方法
     * @param $iterator
     * @param null $pattern
     * @param int $count
     * @return array|bool
     */
    public function scan(&$iterator, $pattern = null, $count = 0) {
        return $this->client->scan($iterator, $pattern, $count);
    }

    /**
     * 通过遍历方式获取集合下内容
     * @param $key
     * @param null $pattern
     * @param int $scanCount
     * @return array
     */
    public function scanSet($key, $pattern = null, $scanCount = 0) {
        $members = [[]];
        $iterator = null;
        while ($scanMembers = $this->client->sScan($key, $iterator, $pattern, $scanCount)) {
            $members[] = $scanMembers;
        }
        return array_merge(...$members);
    }

    /**
     * 集合遍历 通过command方法
     * @param $key
     * @param $iterator
     * @param null $pattern
     * @param int $count
     * @return array|bool
     */
    public function sScan($key, &$iterator, $pattern = null, $count = 0) {
        return $this->client->sScan($key, $iterator, $pattern, $count);
    }

    /**
     * 通过遍历方式获取有序集合下内容
     * @param $key
     * @param null $pattern
     * @param int $scanCount
     * @return array
     */
    public function scanSortSet($key, $pattern = null, $scanCount = 0) {
        $members = [];
        $iterator = null;
        while ($scanMembers = $this->client->zScan($key, $iterator, $pattern, $scanCount)) {
            $members += $scanMembers;
        }

        return $members;
    }

    /**
     * 遍历有序集合
     * @param $key
     * @param $iterator
     * @param null $pattern
     * @param int $count
     * @return array|bool
     */
    public function zScan($key, &$iterator, $pattern = null, $count = 0) {
        return $this->client->zScan($key, $iterator, $pattern, $count);
    }

    /**
     * 通过遍历方式获取哈希值下内容
     * @param $key
     * @param null $pattern
     * @param int $scanCount
     * @return array
     */
    public function scanHash($key, $pattern = null, $scanCount = 0) {
        $members = [[]];
        $iterator = null;
        while ($scanMembers = $this->client->hScan($key, $iterator, $pattern, $scanCount)) {
            $members[] = $scanMembers;
        }
        return array_merge(...$members);
    }

    /**
     * 遍历哈希结果
     * @param $key
     * @param $iterator
     * @param null $pattern
     * @param int $count
     * @return array|bool
     */
    public function hScan($key, &$iterator, $pattern = null, $count = 0) {
        return $this->client->hScan($key, $iterator, $pattern, $count);
    }


    /**
     * 添加排它锁
     * @param $lockName
     * @param int $lockExpire
     * @return bool
     */
    public function addExclusiveLock($lockName, int $lockExpire = 3) {
        $lockName = 'exclusivelock:' . $lockName;
        $retryTimes = 0;
        $maxRetryTimes = $lockExpire > 10 ? 10 : $lockExpire;
        while (false === ($addResult = $this->client->setnx($lockName, 1)) && $retryTimes < $maxRetryTimes) {
            $retryTimes++;
            sleep(1);
        }
        if ($addResult) {
            $this->client->expire($lockName, $lockExpire);
            return true;
        }
        return false;
    }

    /**
     * 删除排它锁
     * @param $lockName
     */
    public function removeExclusiveLock($lockName) {
        $lockName = 'exclusivelock:' . $lockName;
        $this->client->del($lockName);
    }

    /**
     * 执行phpredis中的相关命令
     * @param $method
     * @param $parameters
     * @return mixed
     */
    public function __call($method, $parameters) {
        return $this->command($method, $parameters);
    }
}